<script setup lang="ts" generic="T extends Record<string, any>">
import { ref, computed } from 'vue'
import { ElTable, ElTableColumn, ElButton, ElInput, ElPagination, ElSpace, ElIcon } from 'element-plus'
import { Search, Refresh, Plus } from '@element-plus/icons-vue'

interface Column {
  key: string
  label: string
  width?: number | string
  minWidth?: number | string
  sortable?: boolean
  filterable?: boolean
  type?: 'index' | 'selection' | 'expand'
  formatter?: (row: T, column: any) => string
  render?: (row: T, column: any) => any
}

interface Props {
  data: T[]
  columns: Column[]
  loading?: boolean
  total?: number
  pageSize?: number
  showPagination?: boolean
  showSearch?: boolean
  showRefresh?: boolean
  showAdd?: boolean
  addText?: string
  searchPlaceholder?: string
  height?: number | string
}

const props = withDefaults(defineProps<Props>(), {
  loading: false,
  total: 0,
  pageSize: 20,
  showPagination: true,
  showSearch: true,
  showRefresh: true,
  showAdd: false,
  addText: '新增',
  searchPlaceholder: '请输入搜索关键词',
  height: 'auto'
})

const emit = defineEmits<{
  search: [keyword: string]
  refresh: []
  add: []
  'page-change': [page: number]
  'size-change': [size: number]
  'selection-change': [selection: T[]]
  'row-click': [row: T]
}>()

const searchKeyword = ref('')
const currentPage = ref(1)

const filteredData = computed(() => {
  if (!searchKeyword.value) return props.data
  
  return props.data.filter(item => {
    return Object.values(item).some(value => 
      String(value).toLowerCase().includes(searchKeyword.value.toLowerCase())
    )
  })
})

const handleSearch = () => {
  emit('search', searchKeyword.value)
}

const handleRefresh = () => {
  emit('refresh')
}

const handleAdd = () => {
  emit('add')
}

const handlePageChange = (page: number) => {
  currentPage.value = page
  emit('page-change', page)
}

const handleSizeChange = (size: number) => {
  emit('size-change', size)
}

const handleSelectionChange = (selection: T[]) => {
  emit('selection-change', selection)
}

const handleRowClick = (row: T) => {
  emit('row-click', row)
}
</script>

<template>
  <div class="data-table">
    <div v-if="showSearch || showRefresh || showAdd" class="table-toolbar">
      <div class="toolbar-left">
        <ElSpace>
          <ElInput
            v-if="showSearch"
            v-model="searchKeyword"
            :placeholder="searchPlaceholder"
            clearable
            class="search-input"
            @keyup.enter="handleSearch"
            @clear="handleSearch"
          >
            <template #suffix>
              <ElIcon class="search-icon" @click="handleSearch">
                <Search />
              </ElIcon>
            </template>
          </ElInput>
        </ElSpace>
      </div>
      
      <div class="toolbar-right">
        <ElSpace>
          <ElButton
            v-if="showRefresh"
            type="default"
            :icon="Refresh"
            @click="handleRefresh"
          >
            刷新
          </ElButton>
          
          <ElButton
            v-if="showAdd"
            type="primary"
            :icon="Plus"
            @click="handleAdd"
          >
            {{ addText }}
          </ElButton>
        </ElSpace>
      </div>
    </div>

    <ElTable
      :data="filteredData"
      :loading="loading"
      :height="height"
      @selection-change="handleSelectionChange"
      @row-click="handleRowClick"
      class="main-table"
    >
      <ElTableColumn
        v-for="column in columns"
        :key="column.key"
        :prop="column.key"
        :label="column.label"
        :width="column.width"
        :min-width="column.minWidth || 100"
        :sortable="column.sortable"
        :type="column.type"
      >
        <template v-if="column.render" #default="scope">
          <component :is="column.render(scope.row, column)" />
        </template>
        
        <template v-else-if="column.formatter" #default="scope">
          {{ column.formatter(scope.row, column) }}
        </template>
      </ElTableColumn>
    </ElTable>

    <div v-if="showPagination && total > 0" class="table-pagination">
      <ElPagination
        v-model:current-page="currentPage"
        :page-size="pageSize"
        :total="total"
        :page-sizes="[10, 20, 50, 100]"
        layout="total, sizes, prev, pager, next, jumper"
        @current-change="handlePageChange"
        @size-change="handleSizeChange"
      />
    </div>
  </div>
</template>

<style scoped lang="scss">
.data-table {
  .table-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
    gap: 16px;
    
    .toolbar-left {
      flex: 1;
      
      .search-input {
        width: 300px;
        max-width: 100%;
        
        .search-icon {
          cursor: pointer;
          color: var(--el-text-color-placeholder);
          
          &:hover {
            color: var(--el-color-primary);
          }
        }
      }
    }
    
    .toolbar-right {
      flex-shrink: 0;
    }
  }
  
  .main-table {
    border-radius: 8px;
    overflow: hidden;
    
    :deep(.el-table__header) {
      th {
        background: var(--el-bg-color-page);
        font-weight: 600;
      }
    }
    
    :deep(.el-table__row) {
      cursor: pointer;
      
      &:hover {
        background: var(--el-fill-color-light);
      }
    }
  }
  
  .table-pagination {
    display: flex;
    justify-content: flex-end;
    margin-top: 16px;
  }
}

@media (max-width: 768px) {
  .data-table {
    .table-toolbar {
      flex-direction: column;
      align-items: stretch;
      gap: 12px;
      
      .toolbar-left {
        .search-input {
          width: 100%;
        }
      }
      
      .toolbar-right {
        display: flex;
        justify-content: flex-end;
      }
    }
    
    .main-table {
      :deep(.el-table__body-wrapper) {
        overflow-x: auto;
      }
    }
    
    .table-pagination {
      justify-content: center;
      
      :deep(.el-pagination) {
        flex-wrap: wrap;
        justify-content: center;
      }
    }
  }
}
</style>